package com.magicalcoder.pigeon.mysql.manager.keepalive;

import com.magicalcoder.pigeon.common.cache.DelayItem;
import com.magicalcoder.pigeon.mysql.manager.DbConnection;
import com.magicalcoder.pigeon.mysql.manager.PoolImpl;
import com.magicalcoder.pigeon.mysql.manager.execute.Execute;
import com.magicalcoder.pigeon.mysql.manager.execute.ExecuteSql;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.TimeUnit;

/**
 * Created by hzhedongyu on 2017/6/14.
 * 通过select 1来保证连接不断开
 *
 */
public class SelectOne {

    private long waitTimeout;//mysql数据库等待超时时间

    public SelectOne(long waitTimeout) {
        this.waitTimeout = waitTimeout;
        heartBeat();
    }

    private DelayQueue<DelayItem<PoolImpl.PigeonConnection>> delayQueue = new DelayQueue<DelayItem<PoolImpl.PigeonConnection>>();

    public void putQueue(PoolImpl.PigeonConnection pg){
        //往前推5秒，避免边界值 刚好失效
        long waitTimeoutBefore = waitTimeout - 10000;
        if(waitTimeoutBefore<=0){
            waitTimeoutBefore = waitTimeout;
        }
        long nano = TimeUnit.NANOSECONDS.convert(waitTimeoutBefore,TimeUnit.MILLISECONDS);
        DelayItem<PoolImpl.PigeonConnection> delayItem = new DelayItem<PoolImpl.PigeonConnection>(pg,nano);
        delayQueue.put(delayItem);
    }

    //心跳检测
    private void heartBeat() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (;;) {
                    try {
                        DelayItem<PoolImpl.PigeonConnection> delayItem = delayQueue.take();//取不到内容就会阻塞
                        if (delayItem != null) {
                            PoolImpl.PigeonConnection pg = delayItem.getItem();
                            if(pg.getConnection()!=null){//连接可用
                                DbConnection dbCon = new DbConnection(pg);
                                Execute execute = new ExecuteSql(dbCon);
                                execute.select1();
                                putQueue(pg);//重新入队 等待下一次检测
                            }
                        }
                    } catch (InterruptedException e) {
                        break;
                    }
                }
            }
        });
        thread.setDaemon(true);
        thread.setName("SelectOne-执行select 1避免超时");
        thread.start();
    }


}
